package com.rybbaby.tss.core.utils;


import org.apache.commons.httpclient.util.DateParseException;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 谢进伟
 * @description 日期格式化工具
 * @createDate 2016年12月22日 下午5:00:09
 */
public class DateUtil {

	private static Set<String> dateFormats = new HashSet<>();

	static {
		dateFormats.add("yyyy-MM-dd");
		dateFormats.add("yyyy-MM-dd HH:mm");
		dateFormats.add("yyyy-MM-dd HH:mm:ss");
		dateFormats.add("yyyy-MM-dd HH:mm:ss:SSS");

		dateFormats.add("yyyy/MM/dd");
		dateFormats.add("yyyy/MM/dd HH:mm");
		dateFormats.add("yyyy/MM/dd HH:mm:ss");
		dateFormats.add("yyyy-MM-dd HH:mm:ss:SSS");

		dateFormats.add("yyyy年MM月dd日");
		dateFormats.add("yyyy年MM月dd日 HH:mm");
		dateFormats.add("yyyy年MM月dd日 HH:mm:ss");
		dateFormats.add("yyyy年MM月dd日 HH时mm分");
		dateFormats.add("yyyy年MM月dd日 HH时mm分ss秒");
		dateFormats.add("yyyy年MM月dd日 HH时mm分ss秒SSS毫秒");
	}

	/**
	 * 按指定的格式来格式化指定的日期
	 *
	 * @param date    需要被格式化的日期
	 * @param pattern 日期格式
	 * @return
	 */
	public static String format(Date date, String pattern) {
		if (date == null) {
			return null;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/**
	 * 按指定的格式来格式化当前日期
	 *
	 * @param pattern 日期格式
	 * @return
	 */
	public static String format(String pattern) {
		return format(new Date(), pattern);
	}

	/**
	 * 添加或减去指定的时间给定的日历字段,基于日历的规则。例如,要从当前时间减去5天的日历,你可以实现它通过调用: <br>
	 * Date date=new Date();<br>
	 * DateUtil.add(date,Calendar.DAY_OF_MONTH, -5).
	 *
	 * @param date   起始日期
	 * @param amount 日期或时间的量添加到字段。
	 * @param field  日历字段
	 * @return
	 */
	public static Date add(Date date, int amount, int field) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(field, amount);
		return calendar.getTime();
	}

	/**
	 * 添加或减去当前时间给定的日历字段,基于日历的规则。例如,要从当前时间减去5天的日历,你可以实现它通过调用: <br>
	 * DateUtil.add(Calendar.DAY_OF_MONTH, -5).
	 *
	 * @param amount 日期或时间的量添加到字段。
	 * @param field  日历字段
	 * @return
	 */
	public static Date add(int amount, int field) {
		return add(new Date(), amount, field);
	}

	/**
	 * 将时间字符串转换成date对象
	 *
	 * @param dateStr 日期字符串
	 * @param partten 格式
	 * @return
	 */
	public static Date parse(String dateStr, String partten) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(partten);
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将时间字符串转换成date对象
	 *
	 * @param dateValue 日期字符串
	 * @return
	 */
	public static Date parse(String dateValue) throws DateParseException {
		return parse(dateValue, Collections.emptySet());
	}

	/**
	 * 将时间字符串转换成date对象
	 * @param dateValue   日期字符串
	 * @param dateFormats dateValue 可能的格式
	 * @return
	 * @throws DateParseException
	 */
	public static Date parse(String dateValue, Collection<String> dateFormats) throws DateParseException {
		if (dateFormats == null || (dateFormats != null && dateFormats.isEmpty())) {
			dateFormats = DateUtil.dateFormats;
		}
		SimpleDateFormat dateParser = null;
		Iterator<String> iterator = dateFormats.iterator();
		while (iterator.hasNext()) {
			String format = iterator.next();
			if (dateParser == null) {
				dateParser = new SimpleDateFormat(iterator.next());
			} else {
				dateParser.applyPattern(format);
			}
			try {
				return dateParser.parse(dateValue);
			} catch (ParseException e) {
			}
		}
		throw new DateParseException("Unable to parse the date " + dateValue);
	}


	/**
	 * 计算日期差
	 *
	 * @param startTime
	 * @param endTime
	 * @return
	 * @throws Exception
	 */
	public static double differenceYear(String startTime, String endTime) throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		Calendar bef = Calendar.getInstance();
		Calendar aft = Calendar.getInstance();
		bef.setTime(sdf.parse(startTime));
		aft.setTime(sdf.parse(endTime));
		int result = aft.get(Calendar.MONTH) - bef.get(Calendar.MONTH);
		int month = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR)) * 12;
		double s = (double) Math.abs(month + result) / 12;
		BigDecimal b = new BigDecimal(s);
		double f1 = b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
		return f1;

	}

	/**
	 * 获取当前日期所在周的周一
	 * @param date
	 * @return
	 */
	public static Date getThisWeekMonday(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		// 获得当前日期是一个星期的第几天
		int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
		if (1 == dayWeek) {
			cal.add(Calendar.DAY_OF_MONTH, -1);
		}
		// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		// 获得当前日期是一个星期的第几天
		int day = cal.get(Calendar.DAY_OF_WEEK);
		// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
		cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
		return cal.getTime();
	}

	/**
	 * 获取开始时间结束时间 中所有天数
	 * @param beginDate 开始时间
	 * @param endDate 结束时间
	 * @param format 日期格式 yyyy-MM-dd
	 * @return
	 */
	public static ArrayList<String> getAllDay(String beginDate,String endDate,String format) throws Exception{

		SimpleDateFormat sdf = new SimpleDateFormat(format);
		Calendar cal = Calendar.getInstance();
		cal.setTime(sdf.parse(beginDate));
		ArrayList<String> strings = new ArrayList<>();
		int i = 1;
		for (long d = cal.getTimeInMillis(); d <= sdf.parse(endDate).getTime(); d = get_D_Plaus_1(cal)) {
			i = i+1;
			strings.add(sdf.format(d));
		}
		return strings;
	}
	/**
	 * 设置明天为本月最大时间
	 * @param c
	 * @return
	 */
	public static long get_D_Plaus_1(Calendar c) {
		c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + 1);
		return c.getTimeInMillis();
	}
	/**
	 * 获取开始时间结束时间 中所有天数
	 * @param beginDate 开始时间
	 * @param endDate 结束时间
	 * @param format 日期格式 yyyy-MM-dd
	 * @return
	 */
	public static ArrayList<String> getAllMonth(String beginDate,String endDate,String format) throws Exception{

		SimpleDateFormat sdf = new SimpleDateFormat(format);
		Calendar cal = Calendar.getInstance();
		cal.setTime(sdf.parse(beginDate));
		ArrayList<String> strings = new ArrayList<>();
		int i = 1;
		for (long d = cal.getTimeInMillis(); d <= sdf.parse(endDate).getTime(); d = get_M_Plaus_1(cal)) {
			i = i+1;
			strings.add(sdf.format(d));
		}
		return strings;
	}
	/**
	 * 设置明天为本月最大时间
	 * @param c
	 * @return
	 */
	public static long get_M_Plaus_1(Calendar c) {
		c.set(Calendar.MONTH, c.get(Calendar.MONTH) + 1);
		return c.getTimeInMillis();
	}
}
